package vip.mtdp.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import vip.mtdp.common.CommonConstant;
import vip.mtdp.common.exception.AppRTException;
import vip.mtdp.common.response.CommonResponse;
import vip.mtdp.gateway.service.TokenDTO;
import vip.mtdp.gateway.service.TokenService;

import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author wangguoqing
 * @Description TODO
 * @date 2019/12/6 16:33
 */

@Deprecated
@Slf4j
@Data
//@Component
public class ResponseAuthGatewayFilterFactory implements GlobalFilter, Ordered {

    @Autowired
    private TokenService tokenService;


    /**
     * Process the Web request and (optionally) delegate to the next {@code WebFilter}
     * through the given {@link GatewayFilterChain}.
     *
     * @param exchange the current server exchange
     * @param chain    provides a way to delegate to the next filter
     * @return {@code Mono<Void>} to indicate when request processing is complete
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            ServerHttpRequest request = exchange.getRequest();
            String uri = request.getURI().getPath();
            ServerHttpResponse response = exchange.getResponse();
            /*
            //读取response数据
            //添加code,message
            ServerHttpResponseDecorator serverHttpResponseDecorator = new ServerHttpResponseDecorator(response){
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                        DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                        DataBuffer dataBuffer = dataBufferFactory.join(dataBuffers);
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        //释放内存
                        DataBufferUtils.release(dataBuffer);
                        String jsonContent = new String(content, Charset.forName(CommonConstant.CHARACTER_UTF_8));
                        log.info("uri = {},response = {}",uri,jsonContent);
                        CommonResponse commonResponse = JSONObject.parseObject(jsonContent,CommonResponse.class);
                        // TODO: 2019/12/6 如果是登录接口,返回token,其他接口正常返回
                        if(HttpStatus.OK.value() == Integer.parseInt(commonResponse.getCode())){
                            //成功,生成token
                            TokenDTO tokenDTO = new TokenDTO();
                            String jsonString = JSON.toJSONString(commonResponse.getData());
                            tokenDTO.setJsonData(jsonString);
                            String token = tokenService.createToken(tokenDTO);
                            //将token 设置到 response 中
                            Map<String,Object> map = JSONObject.parseObject(jsonString,Map.class);
                            map.put(CommonConstant.TOKEN_KEY,token);
                            commonResponse.setData(map);
                        }else{
                            //失败,返回403
                            commonResponse.setCode(String.valueOf(HttpStatus.FORBIDDEN));
                        }
                        //重置response数据
                        content = JSON.toJSONBytes(commonResponse);
                        return dataBufferFactory.wrap(content);
                    }));
                }
            };
            */
            //返回
            return chain.filter(exchange.mutate().request(request).response(response).build());
        }catch (Exception e){
            log.error("=====> response error",e);
            CommonResponse<String> commonResponse = new CommonResponse<>();
            //如果是controller抛出AppRTException异常,将异常的code,message返回,若不是AppRTException异常,返回默认的异常
            if(e instanceof AppRTException){
                AppRTException appEx = (AppRTException)e;
                commonResponse.setCode(String.valueOf(appEx.getCode()));
                commonResponse.setMessage(appEx.getMessage());
            }else{
                commonResponse.setCode(String.valueOf(AppRTException.DEFAULT_CODE));
            }
            DataBuffer dataBuffer = exchange.getResponse().bufferFactory().wrap(JSON.toJSONBytes(commonResponse));
            return exchange.getResponse().writeWith(Mono.just(dataBuffer));
        }
    }

    /**
     * Get the order value of this object.
     * <p>Higher values are interpreted as lower priority. As a consequence,
     * the object with the lowest value has the highest priority (somewhat
     * analogous to Servlet {@code load-on-startup} values).
     * <p>Same order values will result in arbitrary sort positions for the
     * affected objects.
     *
     * @return the order value
     * @see #HIGHEST_PRECEDENCE
     * @see #LOWEST_PRECEDENCE
     */
    @Override
    public int getOrder() {
        return 999;
    }
}
